
#ifndef _HTTP_CLIENT_
#define _HTTP_CLIENT_

//#include "httpclient_wrapper.h"
#include "httpclient_def.h"

#ifdef __cplusplus
extern "C" {
#endif

/* HTTP API global definitions */
#ifdef _HTTP_BUILD_AMT
#define CMSI_HTTPCLIENT_PROTOCOL_GUID {0x471b2c0e, 0x6137, 0x4d55, 0x92, 0x36, 0xdd, 0x0f, 0xdb, 0xc2, 0x52, 0xfb}
#endif

/* debug hook */
#define  _HTTP_DEBUGGING_  /* Simply dumps more debugging data to the console */

/* API Version */
#define HTTPCLIENT_VERSION_MINOR           1
#define HTTPCLIENT_VERSION_MAJOR           1

/* Global default sizes */
#define HTTPCLIENT_MAX_SEND_RECV_HEADERS   1024        /* Maximum Send and receive buffers size  */
#define HTTPCLIENT_INIT_SEND_RECV_HEADERS  2048        /* If we can resize the buffers this would be the initial size  */
//#define HTTPCLIENT_MAX_SEND_RECV_HEADERS   640        /* Maximum Send and receive buffers size */
//#define HTTPCLIENT_INIT_SEND_RECV_HEADERS  1024       /* If we can resize the buffers this would be the initial size */

#define HTTPCLIENT_MAX_USERNAME_LENGTH     16          /* Maximum length the user name (host and proxy authentication) */
#define HTTPCLIENT_MAX_PASSWORD_LENGTH     64//16      /* Maximum length  for the password */
/* Maximum length for the base 64 encoded credentials (twice the size of the user name and password max parameters) */
#define HTTPCLIENT_MAX_64_ENCODED_CRED     ((HTTPCLIENT_MAX_USERNAME_LENGTH + HTTPCLIENT_MAX_PASSWORD_LENGTH) * 2) + 4
#define HTTPCLIENT_MAX_CHUNK_HEADER        64          /* Maximum length for the received chunk header (hex - string) size */
#define HTTPCLIENT_MAX_PROXY_HOST_LENGTH   64          /* Maximum length for the proxy host name */
#define HTTPCLIENT_MAX_TOKEN_LENGTH        512         /* Maximum length for an HTTP token data (authentication header elements) */
#define HTTPCLIENT_MAX_TOKEN_NAME_LENGTH   32          /* Maximum length for an HTTP authorization token name ("qop") */
//#define HTTPCLIENT_MAX_HEADER_SEARCH_CLUE  1024      /* Maximum length for a search clue string (Headers searching) */
#define HTTPCLIENT_MAX_HEADER_SEARCH_CLUE  512         /* Maximum length for a search clue string (Headers searching) */
#define HTTPCLIENT_ALLOW_HEAD_VERB         0           /* Can we use the HTTP HEAD verb in our outgoing requests? */

#define HTTPCLIENT_MEMORY_RESIZABLE        FALSE       /* Permission to dynamically resize the headers buffer */
#define HTTPCLIENT_MEMORY_RESIZE_FACTOR    16          /* Factor for memory resizing operation */

#define HTTPCLIENT_DEFAULT_PORT            80          /* Default HTTP port */
#define HTTPCLIENT_DEFAULT_SSL_PORT        443         /* Default HTTPS port */
#define HTTPCLIENT_DEFAULT_VERB            0           /* GET */
#define HTTPCLIENT_DEFAULT_VER             "HTTP/1.1"  /* We will send this in the outgoing header */
#define HTTPCLIENT_DEFAULT_PROXY_VER       "HTTP/1.0"  /* We will send this in the outgoing header (proxy) */
#define HTTPCLIENT_DEFAULT_AGENT           "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)"
#define HTTPCLIENT_DEFAULT_TIMEOUT         30          /* Default timeout in seconds */
#define HTTPCLIENT_DEFAULT_KEEP_ALIVE      30          /* Default Keep-alive value in seconds */
#define HTTPCLIENT_DEFAULT_DIGEST_AUTH     "MD5"       /* This is for bypassing a known bug in AMT05.. */
#define HTTPCLIENT_DEFAULT_PROXY_AUTH      1           /* Basic */

#define HTTPCLIENT_CRLF                    "\r\n"      /* End of line macro */
#define HTTPCLIENT_CRLFX2                  "\r\n\r\n"  /* Double End of line macro */

/* HTTP Session internal API flags */
/* Note: Not intended to be set the by the API user */
#define HTTPCLIENT_FLAG_SECURE             0x00000010 /* The session is secured using TLS */
#define HTTPCLIENT_FLAG_URLANDPORT         0x00000020 /* Url has a port within */
#define HTTPCLIENT_FLAG_URLHTTPS           0x00000040 /* Url has a https prefix */
#define HTTPCLIENT_FLAG_USINGPROXY         0x00000080 /* Operation will be performed using a proxy server */
#define HTTPCLIENT_FLAG_CHUNKED            0x00000100 /* The incoming data is chunked */

/* HTTP Status codes */
#define HTTP_STATUS_OK                              200 /* The request has succeeded */
#define HTTP_STATUS_UNAUTHORIZED                    401 /* The request requires user authentic */
#define HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED   407 /* The client must first authenticate itself with the proxy */

/* Redirection (Note: there are more 30x codes, those are the most popular) */
#define HTTP_STATUS_OBJECT_MOVED                    302 /* Page redirection notification */
#define HTTP_STATUS_OBJECT_MOVED_PERMANENTLY        301 /* Page redirection notification */
#define HTTP_STATUS_CONTINUE                        100 /* Page continue message */

/* MIN AMX macro */
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#define MAX(a,b) (((a) > (b)) ? (a) : (b))

/* HTTP timeout macro for selecting the default value if the caller passed 0 (no timeout) to the function */
//#define HTTP_TIMEOUT(nTimeout) (((nTimeout) > (0)) ? (nTimeout) : (HTTPCLIENT_DEFAULT_TIMEOUT))
#define HTTP_TIMEOUT(nTimeout) (((nTimeout) >= (HTTPCLIENT_DEFAULT_TIMEOUT)) ? HTTPCLIENT_DEFAULT_TIMEOUT : (nTimeout))

#if !defined(ALIGN)
/* 32 bit alignment macro */
#define ALIGN(size) ((size & 0xfffffffc) + ((size & 3) ? 4 : 0))
#endif

#if defined(_HTTP_DEBUGGING_)
    typedef VOID  E_HTTPDebug(const char *,const char*,UINT32,char *,...); /* HTTPDebug hook function */
#endif


/* HTTP API internals structures */

/* Generic parameter structure contains a pointer to the buffer and its length */
typedef struct _httpclientParam_t {
	CHAR *pParam;
	UINT32 nLength;
} httpclientParam_t;

/* HTTP socket events */
typedef struct _httpclientConnection_t {
	fd_set FDRead;             /* socket read event */
	fd_set FDWrite;            /* socket write event */
	fd_set FDError;            /* socket error event */
	INT32  HttpSocket;         /* The underling socket */
	UINT32 HttpStartTime;      /* Time stamp for the session */
	UINT32 HttpClientPort;     /* For client side binding */
	BOOL   TlsNego;            /* TLS negotiation flag */
	long   TlsDataParams;      /* For tls */
} httpclientConnection_t;

/* Request URL */
typedef struct _httpclientUrl_t {
	httpclientParam_t UrlBsee;           /* a pointer and length to the "http" section of the URL */
	httpclientParam_t UrlHost;           /* a pointer and length to the host section of the URL */
	httpclientParam_t UrlPort;           /* a pointer and length to the PORT (if was specified section) */
	httpclientParam_t UrlRequest;        /* a pointer and length of the request section of the URL */
	UINT16            nPort;             /* the PORT that we should use (could be default or the one found within the URL) */
	CHAR              Url[HTTPCLIENT_MAX_URL_LENGTH];   /* a buffer for the URL */
} httpclientUrl_t;

/* HTTP headers (incoming and outgoing) */
typedef struct _httpclientHeaders_t {
    httpclientParam_t HeadersBuffer;     /* a pointer and length of the complete Headers (in\out) buffer */
    httpclientParam_t HeadersOut;        /* a pointer and length of the outgoing HTTP headers */
    httpclientParam_t HeadersIn;         /* a pointer and length of the incoming headers */
    httpclientParam_t HeaderSearch;      /* Index and pointer for the header search functions */
    httpclientVerb_e  HttpVerb;          /* the HTTP verb that was used in the session */
    httpclientVerb_e  HttpLastVerb;      /* the HTTP verb that was last transmited to the server */
    CHAR              SearchClue[HTTPCLIENT_MAX_HEADER_SEARCH_CLUE];
    CHAR              Verb[16];          /* the actual string buffer of the HTTP verb */
} httpclientHeaders_t;

/* HTTP headers (parsed headers information) */
typedef struct _httpclientHeadersInfo_t {
    httpclientParam_t HttpRedirectURL;        /* Stores the redirection URL if we got a 301 or 303 return code */
    UINT32            nHTTPStatus;            /* the HTTP status code (200 401 407 act') */
    UINT32            nHTTPContentLength;     /* the Content length if specified of the returned data */
    UINT32            nHTTPPostContentLength; /* the Content-Length of the POSTed data (if known) */
    BOOL              Connection;             /* True = Keep alive or undefined, False = Closed */
    BOOL              ValidHeaders;           /* a flag that indicates if the incoming header ware parsed OK and found to be valid */
    BOOL              HaveCredentials;        /* a flag that indicates if we have credentials for the session */
    CHAR              HTTPVersion[16];        /* HTTP version string buffer (for example: "HTTP 1.1") */
} httpclientHeadersInfo_t;

/* Authentication parameters that ware extracted from the incoming headers */
typedef struct _httpclientAuthHeader_t {
    httpclientParam_t   AuthHeader;             /* the pointer and length of the authentication header */
    UINT32              httpclientAuthSchema_e; /* Its schema (could be any of the supported) */
} httpclientAuthHeader_t;

/* Proxy related data */
typedef struct _httpclientProxy_t {
    CHAR                   ProxyHost[HTTPCLIENT_MAX_PROXY_HOST_LENGTH];
    CHAR                   ProxtUser[HTTPCLIENT_MAX_USERNAME_LENGTH];
    CHAR                   ProxyPassword[HTTPCLIENT_MAX_PASSWORD_LENGTH];
    UINT16                 nProxyPort;
    CHAR                   AuthSchemaName[16];  /* The authentication schema name (for string comperission) */
    httpclientAuthSchema_e ProxyAuthSchema;
} httpclientProxy_t;

/* HTTP Type Definitions */
typedef UINTP          HTTPCLIENT_SESSION_HANDLE;
typedef UINT32          HTTPCLIENT_SESSION_FLAGS;


/**
 * \brief HTTP Session Initialization.
 *
 * \details Allocate memory for a new HTTP Session.
 *
 * \param flags[in] Http flags.
 *
 * \return http client Session handle.
 *
 * \attention (1) This function must be called before any others interface, and should be called once only.
 */
HTTPCLIENT_SESSION_HANDLE httpclient_open    (HTTPCLIENT_SESSION_FLAGS Flags);
/**
 * \brief HTTP Session Reset.
 *
 * \details Reset the HTTP session and make it ready for another call.
 *
 * \param pSession[in] HTTP Session Handle.
 *
 * \return Please refer to #HTTPCLIENT_RESULT.
 */
HTTPCLIENT_RESULT  httpclient_reset(HTTPCLIENT_SESSION_HANDLE pSession);
/**
 * \brief HTTP Session Close.
 *
 * \details Reset the HTTP session and make it ready for another call.
 *
 * \param flags[in] Http flags.
 *
 * \return Please refer to #HTTPCLIENT_RESULT.
 */
HTTPCLIENT_RESULT httpclient_close    (HTTPCLIENT_SESSION_HANDLE *pSession);

/**
 * \brief Http Session Verb Set.
 *
 * \details Sets the HTTP verb for the outgoing request.
 *
 * \param pSession[in] HTTP Session Handle.
 * \param HttpVerb[in] Refer to #httpclientVerb_e.
 *
 * \return Please refer to #HTTPCLIENT_RESULT.
 */
HTTPCLIENT_RESULT httpclient_set_verb(HTTPCLIENT_SESSION_HANDLE pSession, httpclientVerb_e HttpVerb);

/**
 * \brief Http Session Auth Set.
 *
 * \details Sets the HTTP authentication schema.
 *
 * \param pSession[in]   HTTP Session Handle.
 * \param AuthSchema[in] Refer to #httpclientAuthSchema_e.
 * \param pReserved[in]  CredPassword.
 *
 * \return Please refer to #HTTPCLIENT_RESULT.
 */
HTTPCLIENT_RESULT httpclient_set_auth      (HTTPCLIENT_SESSION_HANDLE pSession, httpclientAuthSchema_e AuthSchema, void *pReserved);

/**
 * \brief Http Session Proxy Set.
 *
 * \details Sets all the proxy related parameters.
 *
 * \param pSession    [in]HTTP Session Handle.
 * \param pProxyHost  [in]Null terminated string containing the host name.
 * \param nPort       [in]The proxy port number.
 * \param pUserName   [in]User name for proxy authentication (can be null).
 * \param pPassword   [in]User password for proxy authentication (can be null).
 *
 * \return Please refer to #HTTPCLIENT_RESULT.
 */
HTTPCLIENT_RESULT httpclient_set_proxy      (HTTPCLIENT_SESSION_HANDLE pSession, CHAR *pProxyName, UINT16 nPort, CHAR *pUserName, CHAR *pPassword);

/**
 * \brief Http Session Credentials Set.
 *
 * \details Sets credentials for the target host.
 *
 * \param pSession    [in]HTTP Session Handle.
 * \param pUserName   [in]Null terminated string containing the sessions user name.
 * \param pPassword   [in]Null terminated string containing the sessions password.
 *
 * \return Please refer to #HTTPCLIENT_RESULT.
 */
HTTPCLIENT_RESULT httpclient_set_credentials(HTTPCLIENT_SESSION_HANDLE pSession, CHAR *pUserName, CHAR *pPassword);

/**
 * \brief Http Session Headers Set.
 *
 * \details Add headers to the outgoing request.
 *
 * \param pSession    [in]HTTP Session Handle.
 * \param pHeaderName [in]The Headers name.
 * \param pHeaderData [in]The headers data.
 * \param nInsert     [in]Reserved could be any.
 *
 * \return Please refer to #HTTPCLIENT_RESULT.
 */
HTTPCLIENT_RESULT httpclient_add_headers   (HTTPCLIENT_SESSION_HANDLE pSession, CHAR *pHeaderName, CHAR *pHeaderData, BOOL nInsert);

/**
 * \brief Http Session Request Send.
 *
 * \details This function builds the request headers, performs a DNS resolution ,
 *          opens the connection (if it was not opened yet by a previous request or if it has closed)
 *          and sends the request headers.
 * \param pSession    [in]HTTP Session Handle.
 * \param pUrl        [in]The requested URL.
 * \param pData       [in]Data to post to the server.
 * \param nDataLength [in]Length of posted data.
 * \param TotalLength [in]
 * \param nTimeout    [in]Operation timeout.
 * \param nClientPort [in]Client side port 0 for none.
 *
 * \return Please refer to #HTTPCLIENT_RESULT.
 */
HTTPCLIENT_RESULT httpclient_send_request      (HTTPCLIENT_SESSION_HANDLE pSession, CHAR *pUrl, VOID *pData, UINT32 nDataLength, UINT32 TotalLength, UINT32 nTimeout,UINT32 nClientPort);

/**
 * \brief Http Session Response Receive.
 *
 * \details Receives the response header on the connection and parses it,
 *          Performs any required authentication.
 * \param pSession    [in]HTTP Session Handle.
 * \param nTimeout    [in]Timeout for the operation.
 *
 * \return Please refer to #HTTPCLIENT_RESULT.
 */
HTTPCLIENT_RESULT httpclient_recv_response      (HTTPCLIENT_SESSION_HANDLE pSession, UINT32 nTimeout);

/**
 * \brief Http Session Data Send.
 *
 * \details Send data to the remote server.
 *
 * \param pSession      [in]HTTP Session Handle.
 * \param pBuffer       [in]The buffer will be send.
 * \param nBufferLength [in]Buffer size.
 * \param nTimeout      [in]Timeout for the operation.
 *
 * \return Please refer to #HTTPCLIENT_RESULT.
 */
HTTPCLIENT_RESULT httpclient_send_data      (HTTPCLIENT_SESSION_HANDLE pSession, VOID *pBuffer, UINT32 nBufferLength, UINT32 nTimeout);

/**
 * \brief Http Session Data Receive.
 *
 * \details Receives data from the server. Parse out the chunks data.
 *
 * \param pSession      [in]HTTP Session Handle.
 * \param pBuffer       [inout]a pointer to a buffer that will be filled with the servers response.
 * \param nBytesToRead  [in]The size of the buffer (numbers of bytes to read).
 * \param nTimeout      [in]operation timeout in seconds.
 * \param nBytesRecived [out]Count of the bytes that ware received in this operation.
 *
 * \return Please refer to #HTTPCLIENT_RESULT.
 */
HTTPCLIENT_RESULT httpclient_receive_data      (HTTPCLIENT_SESSION_HANDLE pSession, VOID *pBuffer, UINT32 nBytesToRead, UINT32 nTimeout, UINT32 *nBytesRecived);

/**
 * \brief Http Session Information Get.
 *
 * \details Get the session information.
 *
 * \param pSession   [in]HTTP Session Handle.
 * \param HTTPClient [out]session information, refer to #httpclient_t.
 *
 * \return Please refer to #HTTPCLIENT_RESULT.
 */
HTTPCLIENT_RESULT httpclient_get_info     (HTTPCLIENT_SESSION_HANDLE pSession, httpclient_t *pHTTPClient);

#if 0
HTTPCLIENT_RESULT httpclient_find_first_header(HTTPCLIENT_SESSION_HANDLE pSession, CHAR *pSearchClue,CHAR *pHeaderBuffer, UINT32 *nLength);
HTTPCLIENT_RESULT httpclient_get_next_header(HTTPCLIENT_SESSION_HANDLE pSession, CHAR *pHeaderBuffer, UINT32 *nLength);
HTTPCLIENT_RESULT httpclient_find_close_header(HTTPCLIENT_SESSION_HANDLE pSession);
#endif

#if defined(_HTTP_DEBUGGING_)
/**
 * \brief HTTP Session Close.
 *
 * \details Sets the HTTP debug function pointer.
 *
 * \param pSession[in]   HTTP Session Handle.
 * \param pDebugFunc[in] Function pointer to the the caller debugging function.
 *
 * \return Please refer to #HTTPCLIENT_RESULT.
 */
HTTPCLIENT_RESULT httpclient_set_debughook       (HTTPCLIENT_SESSION_HANDLE pSession, E_HTTPDebug *pDebug);
#endif

#ifdef __cplusplus
}
#endif

#endif //_HTTP_CLIENT_
